import java.io.*;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;


public class HLR_sim {
	
    public static void main(String[] args) throws IOException {
    	Signal actSignal;
    	
    	FileWriter fstream;
    	BufferedWriter measurementFile;
    	
    	try{
    	    fstream = new FileWriter("measurementFile.txt");
    	    measurementFile = new BufferedWriter(fstream);	
    	
	    	ArrivalProcessor arrivalProcessor = new ArrivalProcessor(measurementFile);
	    	Gen_LU_request Generator = new Gen_LU_request();
	
	    	Generator.sendTo = arrivalProcessor;
	    	
	    	SignalList.list = new Signal();
	    	SignalList.last = new Signal();
	    	SignalList.list.next = SignalList.last;
	    	
	    	SignalList.SendSignal(G.READY, Generator, G.time + G.ARRIVAL_TIME_RETRIAL_1); 
	    //	SignalList.SendSignal(G.READY, Generator, G.time + G.LU_REQUEST_ARRIVAL_TIME);  
	    	SignalList.SendSignal(G.MEASURE, arrivalProcessor, G.time + G.MEASUREMENT_TIME);
	    	
	    	while (G.time < G.SIMULATION_TIME){
	    		actSignal = SignalList.FetchSignal();
	    		G.time = actSignal.arrivalTime;
	    		actSignal.destination.TreatSignal(actSignal);
	    	}

    	
	    	double accumulateAll = 0;
	    	double accumulate0 = 0;
	    	double accumulate1 = 0;
	    	double accumulate2 = 0;
	    	
	    	//int numberRejectedTotal = 0;
	    	//int numberMaxUpdate = 0;
	    	
	    	for(int i = 0; i < G.NUMBER_OF_DB_PROCESSORS; i++) {
	    		//all
	    		double jobsInQueueI = (arrivalProcessor.accumulatedJobs0[i]+arrivalProcessor.accumulatedJobs1[i]+arrivalProcessor.accumulatedJobs2[i])/arrivalProcessor.noMeasurements;
	        	System.out.println("Mean number of jobs in queue " + (i) + " is " + Double.toString(jobsInQueueI));    
	        	accumulateAll += jobsInQueueI;
	        	//jobs0
	        	double jobs0InQueueI = (arrivalProcessor.accumulatedJobs0[i])/arrivalProcessor.noMeasurements;
	        	System.out.println("Mean number of jobs Type 0 in queue " + (i) + " is " + Double.toString(jobs0InQueueI));    
	        	accumulate0 += jobs0InQueueI;
	        	//jobs1
	        	double jobs1InQueueI = (arrivalProcessor.accumulatedJobs1[i])/arrivalProcessor.noMeasurements;
	        	System.out.println("Mean number of jobs Type 1 in queue " + (i) + " is " + Double.toString(jobs1InQueueI));    
	        	accumulate1 += jobs1InQueueI;
	        	//jobs2
	        	double jobs2InQueueI = (arrivalProcessor.accumulatedJobs2[i])/arrivalProcessor.noMeasurements;
	        	System.out.println("Mean number of jobs Type 2 in queue " + (i) + " is " + Double.toString(jobs2InQueueI));    
	        	accumulate2 += jobs2InQueueI;
	        	
	        //	numberRejectedTotal += (arrivalProcessor.dbProcessorNetwork[i]).numberOfRejected;
	        	
	        	//numberMaxUpdate += (arrivalProcessor.dbProcessorNetwork[i]).numberMaxUpdate;
	    	}
	    	
	    	// Little's theroem: lambda = N/T
	    	//					 lambda ... arrival rate
	    	//					 T ... average time a customer spends in the system
	    	//					 N ... storage
	
	     	System.out.println("Mean number of jobs in all queues is " + Double.toString((double)accumulateAll/G.NUMBER_OF_DB_PROCESSORS));
	     	System.out.println("Mean number of job 0 in all queues is " + Double.toString((double)accumulate0/G.NUMBER_OF_DB_PROCESSORS));
	     	System.out.println("Mean number of job 1 in all queues is " + Double.toString((double)accumulate1/G.NUMBER_OF_DB_PROCESSORS));
	     	System.out.println("Mean number of job 2 in all queues is " + Double.toString((double)accumulate2/G.NUMBER_OF_DB_PROCESSORS));
	     	
	      	System.out.println("Location Updates in Database Processor 1 " + Double.toString((double)ArrivalProcessor.dbProcessorNetwork[1].locationUpdateDb));  	
	
	     	System.out.println("Total number of rejected updates " + Integer.toString(G.numberRejected));
	     	System.out.println("Number of updates which needed more than 0.1s is " + Integer.toString(G.numberMaxUpdate));
	     
	     	System.out.println("Mean number of busy servers " + Double.toString((double)(arrivalProcessor.busyServers)/arrivalProcessor.noMeasurements));
	     	System.out.println("Calculate rate from busy servers: lambda = Ns/(x1 + x2) " + Double.toString((double)(arrivalProcessor.busyServers)/(arrivalProcessor.noMeasurements*(G.SERVICE_TIME_JOB1 + G.SERVICE_TIME_JOB2))));
	     	
	     	System.out.println("Average time T a job spends in the system in " + Double.toString((double)G.avTime/G.numberOfUpdates));
	     	
	     	System.out.println("Number of updates per second (Troughput) " + Double.toString((double)G.numberOfUpdates/G.time));
	     	System.out.println("Average time T a job spends in the system in " + Double.toString((double)G.time/G.numberOfUpdates));
	     	System.out.println("Average # N of jobs during the interval " + Double.toString((double)G.numberOfUpdates/arrivalProcessor.numberArrivals)); 
	     	System.out.println("Little's theorem: lambda = N/T = " + Double.toString(((double)G.numberOfUpdates/arrivalProcessor.numberArrivals)*((double)G.numberOfUpdates/G.time))); 
	     	
	     	measurementFile.close();
    	
	    }catch (Exception e){
	    	System.err.println("Error: " + e.getMessage());
	    }
    }
}